/* file name  : STUNTMessage.java
 * created    : Fri 23 Sep 2005 05:40:28 AM EDT
 * authors    : Saikat Guha <saikat@cs.cornell.edu>
 * copyright  : GNU Lesser General Public License version 2.1 or later
 *
 * Copyright (C) 2005 Saikat Guha <saikat@cs.cornell.edu>
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307 USA
 *
 */
package net.nutss.stunt;

import java.net.SocketAddress;

/**
 * STUNT message sent over signaling channel.
 *
 * @author Saikat Guha
 * @version %I%, %G%
 */
class STUNTMessage implements java.io.Serializable {

    /**
    * STUNT message type
    */
    enum Stage {
        /** Invite remote TCP peer */
        STUNT_INVITE,

        /** Accept TCP invitation */
        STUNT_ACCEPT,

        /** Acknowledge TCP socket establishment */
        STUNT_ESTABLISHED,

        /** Request TCP callback */
        STUNT_CALLBACK,

        /** Signal TCP fatal error */
        STUNT_ABORT,

        /** Request TCP active/passive role reversal */
        STUNT_SWAP,

        /** Invite remote UDP peer */
        STUN_INVITE,

        /** Accept UDP invitation */
        STUN_ACCEPT,

        /** Acknowledge UDP socket establishment */
        STUN_ESTABLISHED,

        /** Signal UDP sockets are ready */
        STUN_READY,

        /** Signal UDP fatal error */
        STUN_ABORT,

        /** Request UDP active/passive role reversal */
        STUN_SWAP
    };

    /**
     * Type of the STUNT signaling message
     */
    Stage stage;

    /**
     * External address and port predicted by the sender. Valid only in INVITE
     * and ACCEPT packets.
     */
    SocketAddress pred;

    static final long serialVersionUID = 0;

    public String toString() {
        return String.format("{stage=%s pred=%s}", stage, pred);

    }

    /**
     * Sets the fields in the message
     *
     * @param stage type of the message
     * @param pred predicted port, if any
     * @return this message
     */
    private STUNTMessage set(Stage stage, java.net.InetSocketAddress pred) {
        this.stage = stage;
        this.pred = pred;
        return this;
    }


    /**
     * Changes message to an INVITE
     *
     * @param pred predicted port
     * @return this message
     */
    STUNTMessage invite(java.net.InetSocketAddress pred) { return set(Stage.STUNT_INVITE, pred); }

    /**
     * Changes message to an INVITE
     *
     * @param pred predicted port
     * @return this message
     */
    STUNTMessage inviteUDP(java.net.InetSocketAddress pred) { return set(Stage.STUN_INVITE, pred); }

    /**
     * Changes message to an ACCEPT
     *
     * @param pred predicted port
     * @return this message
     */
    STUNTMessage accept(java.net.InetSocketAddress pred) { return set(Stage.STUNT_ACCEPT, pred); }

    /**
     * Changes message to an ACCEPT
     *
     * @param pred predicted port
     * @return this message
     */
    STUNTMessage acceptUDP(java.net.InetSocketAddress pred) { return set(Stage.STUN_ACCEPT, pred); }

    /**
     * Changes message to an ESTABLISHED
     *
     * @return this message
     */
    STUNTMessage established() { return set(Stage.STUNT_ESTABLISHED, null); }

    /**
     * Changes message to an ESTABLISHED
     *
     * @return this message
     */
    STUNTMessage establishedUDP() { return set(Stage.STUN_ESTABLISHED, null); }

    /**
     * Changes message to an CALLBACK
     *
     * @return this message
     */
    STUNTMessage callback() { return set(Stage.STUNT_CALLBACK, null); }

    /**
     * Changes message to an SWAP
     *
     * @return this message
     */
    STUNTMessage swap() { return set(Stage.STUNT_SWAP, null); }

    /**
     * Changes message to an SWAP
     *
     * @return this message
     */
    STUNTMessage swapUDP() { return set(Stage.STUN_SWAP, null); }

    /**
     * Changes message to an ABORT
     *
     * @return this message
     */
    STUNTMessage abort() { return set(Stage.STUNT_ABORT, null); }

    /**
     * Changes message to an ABORT
     *
     * @return this message
     */
    STUNTMessage abortUDP() { return set(Stage.STUN_ABORT, null); }

    /**
     * Changes message to an READY
     *
     * @return this message
     */
    STUNTMessage readyUDP() { return set(Stage.STUN_READY, null); }
}
